﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using Camera;

namespace DebugLibrary
{
    
    public class DrawApi3D
    {

        GraphicsDevice device = null;
        CameraService cameraService = null;

        public void Initialize(GraphicsDevice device, CameraService cameraService)
        {
            this.device = device;
            this.cameraService = cameraService;
        }

        public void DrawLine(float x1, float y1, float z1, float x2, float y2, float z2)
        {
            this.DrawLine(new Vector3(x1, y1, z1), new Vector3(x2, y2, z2));
        }

        public void DrawLine(float x1, float y1, float z1, float x2, float y2, float z2, Color color)
        {
            this.DrawLine(new Vector3(x1, y1, z1), new Vector3(x2, y2, z2), color);
        }

        public void DrawLine(Vector3 start, Vector3 end)
        {

            this.DrawLine(start, end, Color.White);

        }

        public void DrawLine(Vector3 start, Vector3 end, Color color)
        {

            var vertices = new[] {new VertexPositionColor(start, color), new VertexPositionColor(end, color) };
            device.DrawUserPrimitives(PrimitiveType.LineList, vertices, 0, 1);

        }

        public void DrawCube(Vector3 position, float Height, float Length, float Width, Matrix orientation, Color color)
        {

            float HeightOwer2 = Height / 2;
            float LengthOwer2 = Length / 2;
            float WidthOwer2 = Width / 2;

            Vector3 p1 = new Vector3(- LengthOwer2, - WidthOwer2, - HeightOwer2);
            Vector3 p2 = new Vector3(+ LengthOwer2, - WidthOwer2, - HeightOwer2);
            Vector3 p3 = new Vector3(+ LengthOwer2, + WidthOwer2, - HeightOwer2);
            Vector3 p4 = new Vector3(- LengthOwer2, + WidthOwer2, - HeightOwer2);
            Vector3 p5 = new Vector3(- LengthOwer2, - WidthOwer2, + HeightOwer2);
            Vector3 p6 = new Vector3(+ LengthOwer2, - WidthOwer2, + HeightOwer2);
            Vector3 p7 = new Vector3(+ LengthOwer2, + WidthOwer2, + HeightOwer2);
            Vector3 p8 = new Vector3(- LengthOwer2, + WidthOwer2, + HeightOwer2);

            p1 = Vector3.Transform(p1, orientation);
            p2 = Vector3.Transform(p2, orientation);
            p3 = Vector3.Transform(p3, orientation);
            p4 = Vector3.Transform(p4, orientation);
            p5 = Vector3.Transform(p5, orientation);
            p6 = Vector3.Transform(p6, orientation);
            p7 = Vector3.Transform(p7, orientation);
            p8 = Vector3.Transform(p8, orientation);

            p1 += position;
            p2 += position;
            p3 += position;
            p4 += position;
            p5 += position;
            p6 += position;
            p7 += position;
            p8 += position;

            DrawLine(p1, p2, color);
            DrawLine(p2, p3, color);
            DrawLine(p3, p4, color);
            DrawLine(p4, p1, color);

            DrawLine(p5, p6, color);
            DrawLine(p6, p7, color);
            DrawLine(p7, p8, color);
            DrawLine(p8, p5, color);

            DrawLine(p1, p5, color);
            DrawLine(p2, p6, color);
            DrawLine(p3, p7, color);
            DrawLine(p4, p8, color);

        }

        public void DrawPoint(float x, float y, float z, Color color)
        {

            Vector3 pointPos = new Vector3(x, y, z);

            var vertices = new[] { new VertexPositionColor(pointPos, color), new VertexPositionColor(GetEndPointForDot(pointPos), color) };

            device.DrawUserPrimitives(PrimitiveType.LineList, vertices, 0, 1);
        }

        private Vector3 GetEndPointForDot(Vector3 start)
        {
            // Convert start point to screen space
            Vector3 screenPoint = device.Viewport.Project(start, cameraService.getProjection(), cameraService.getView(), Matrix.Identity);

            // Screen space is defined in pixels so adding (1,0,0) moves it right one pixel
            screenPoint += Vector3.Right;

            // Finally unproject it back into world space
            return device.Viewport.Unproject(screenPoint, cameraService.getProjection(), cameraService.getView(), Matrix.Identity);
        }

    }
}
